package com.ilearn.iodata.iolingo.service.processor;

import com.ilearn.iodata.iolingo.service.GetCollectionService;
import com.ilearn.iodata.iolingo.service.GetEntityService;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.data.EntityCollection;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.*;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.SerializerResult;
import org.apache.olingo.server.api.uri.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * http://localhost:8081/chinabond.svc/members(id=1)?$select=first_name,last_name
 * 经测试，带括号查询的这种方式，不能带$orderby $top $skip $filter ，所以如果是存储过程，那么分页参数应该是存储过程本身就支持才行
 * 可以使用$select，用来对存储过程的结果进行二次过滤。
 */
@Service
public class GenericEntityProcessor extends GenericODataBaseProcessor implements EntityProcessor {

    private OData odata;
    private ServiceMetadata serviceMetadata;

    @Autowired
    private GetEntityService getEntityService;

    @Autowired
    private GetCollectionService getCollectionService;

    @Override
    public void init(OData odata, ServiceMetadata serviceMetadata) {
        this.odata = odata;
        this.serviceMetadata = serviceMetadata;
    }

    @Override
    public void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException {
        // 1. retrieve the Entity Type
        List<UriResource> resourcePaths = uriInfo.getUriResourceParts();

        final UriResource lastItem = resourcePaths.get(resourcePaths.size() - 1);

        UriResourceKind kind = lastItem.getKind();
        // Note: only in our example we can assume that the first segment is the EntitySet
        UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0);
        EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();

        // 括号传参键值对
        List<UriParameter> keyPredicates = uriResourceEntitySet.getKeyPredicates();
        EntityCollection entitySet = getCollectionByKey(getCollectionService, edmEntitySet, keyPredicates);

        // 3. serialize
        ODataSerializer serializer = odata.createSerializer(responseFormat);
        ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).suffix(ContextURL.Suffix.ENTITY).build();


        EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions
                .with().contextURL(contextUrl).build();
        SerializerResult serializerResult = serializer.entityCollection(
                this.serviceMetadata, edmEntitySet.getEntityType(), entitySet, opts);


        // expand and select currently not supported
        /*EntitySerializerOptions options = EntitySerializerOptions.with().contextURL(contextUrl).build();
        SerializerResult result = serializer.entity(serviceMetadata, entityType, entity, options);*/

        //4. configure the response object
        populateResponseForFormat(response, responseFormat, serializerResult);
    }


    /*private EntityCollection getCollectionByKey(EdmEntitySet edmEntitySet, List<UriParameter> keyPredicates) {

        List<EdmKeyPropertyRef> keyPropertyRefs = edmEntitySet.getEntityType().getKeyPropertyRefs();

        EntityCollection entityCollection = new EntityCollection();

        List<Entity> entities = entityCollection.getEntities();


        String entitySetName = edmEntitySet.getName();

        StringBuilder sql = new StringBuilder();
        sql.append("select * from ");
        sql.append(entitySetName);
        sql.append(" where 1=1");


        for (EdmKeyPropertyRef edmKeyPropertyRef : edmEntitySet.getEntityType().getKeyPropertyRefs()) {
            System.out.println("edmKeyName:" + edmKeyPropertyRef.getName() + " alias:" + edmKeyPropertyRef.getAlias());
            System.out.println("type:" + edmKeyPropertyRef.getProperty().getType());
            System.out.println("kind:" + edmKeyPropertyRef.getProperty().getType().getKind());
        }

        for (UriParameter keyPredicate : keyPredicates) {

            System.out.println("alias:" + keyPredicate.getAlias());
            System.out.println("name:" + keyPredicate.getName());
            System.out.println("expression" + keyPredicate.getExpression());
            System.out.println("referProp:" + keyPredicate.getReferencedProperty());
            System.out.println("text:" + keyPredicate.getText());


            String keyPredicateVal = keyPredicate.getText();
            final EdmKeyPropertyRef keyPropertyRef = edmEntitySet.getEntityType().getKeyPropertyRef(keyPredicate.getName());

            System.out.println("keyType:" + keyPropertyRef.getProperty().getType().getFullQualifiedName());
            System.out.println("edmType:"+ EdmPrimitiveTypeKind.Date.getFullQualifiedName());
            if (keyPropertyRef.getProperty().getType().getFullQualifiedName().equals(EdmPrimitiveTypeKind.Date.getFullQualifiedName())) {
                keyPredicateVal = OlingoUtil.mkString(keyPredicateVal, "'");
            }

            System.out.println("加工后：" + keyPredicateVal);

            sql.append(" and " + keyPredicate.getName() + "=" + keyPredicateVal); // + keyPredicate.getText()
        }

        String sqlStatement = sql.toString();
        System.out.println("》》》》》》》》》 " + sqlStatement + " 《《《《《《《《《《《《《《《");
        entities.addAll(getCollectionService.getCollectionByJdbcTemplate(sqlStatement, entitySetName, keyPropertyRefs));
        return entityCollection;
    }*/

    @Override
    public void createEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException {

    }

    @Override
    public void updateEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException {

    }

    @Override
    public void deleteEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException, ODataLibraryException {

    }
}
